package com.derbysoft.ota.application.translator.rs;

import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;

import com.derbysoft.modules.eip.translator.Translator;
import com.derbysoft.ota.application.util.Functions;
import com.derbysoft.ota.interfaces.protocol._2009a.AddressInfoType;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelSearchRQ;
import com.derbysoft.ota.interfaces.protocol._2009a.PropertiesType;
import com.derbysoft.ota.interfaces.protocol._2009a.BasicPropertyInfoType.ContactNumbers;
import com.derbysoft.ota.interfaces.protocol._2009a.BasicPropertyInfoType.Policy;
import com.derbysoft.ota.interfaces.protocol._2009a.BasicPropertyInfoType.Position;
import com.derbysoft.ota.interfaces.protocol._2009a.PropertiesType.Property;
import com.derbysoft.ota.interfaces.protocol._2009a.PropertyValueMatchType.RateRange;
import com.derbysoft.remote.dswitch.generic.dto.AddressDTO;
import com.derbysoft.remote.dswitch.generic.dto.PositionDTO;
import com.derbysoft.remote.dswitch.generic.dto.TelephoneDTO;
import com.derbysoft.remote.dswitch.hotel.dto.HotelPolicyDTO;
import com.derbysoft.remote.dswitch.hotel.dto.HotelPropertyInfoDTO;
import com.derbysoft.remote.dswitch.hotel.dto.HotelSearchPropertyDTO;
import com.derbysoft.remote.dswitch.hotel.dto.ProviderRateInfoDTO;
import com.googlecode.functionalcollections.FunctionalIterables;
import com.googlecode.functionalcollections.Injector;

public class HotelPropertyTranslator implements Translator<Entry<OTAHotelSearchRQ, HotelSearchPropertyDTO>, PropertiesType.Property> {
  
	private static RateRangeTranslator rateRangeTranslator = new RateRangeTranslator();

	@Override
    public Property translate(Entry<OTAHotelSearchRQ, HotelSearchPropertyDTO> source) {
        Property propertyDest = new PropertiesType.Property();
        HotelSearchPropertyDTO propertySource = source.getValue();
		HotelPropertyInfoDTO hotelPropertyInfo = propertySource.getHotelPropertyInfo();
        propertyDest.setBrandCode(hotelPropertyInfo.getHotelBasicInfo().getHotelRef().getBrandCode());
        propertyDest.setChainCode(hotelPropertyInfo.getHotelBasicInfo().getHotelRef().getChainCode());
        propertyDest.setHotelCode(hotelPropertyInfo.getHotelBasicInfo().getHotelRef().getCode());
        propertyDest.setHotelName(hotelPropertyInfo.getHotelBasicInfo().getHotelRef().getName());
        propertyDest.setHotelCityCode(cityCode(source.getKey()));
        propertyDest.setAddress(addressInfo(hotelPropertyInfo.getHotelBasicInfo().getAddress()));
        propertyDest.setContactNumbers(contactNumber(hotelPropertyInfo.getContactNumbers()));
        propertyDest.setPolicy(policy(hotelPropertyInfo.getHotelPolicy()));
        propertyDest.setPosition(position(hotelPropertyInfo.getHotelBasicInfo().getPosition()));
        propertyDest.getRateRange().addAll(rateRange(propertySource.getProviderRateInfos()));

        //TODO : HotelAmenity, Service? OTA use code but we use name!

        return propertyDest;
    }

    private String cityCode(OTAHotelSearchRQ otaHotelSearchRQ) {
    	return otaHotelSearchRQ.getCriteria().getCriterion().iterator().next().getHotelRef().iterator().next().getHotelCityCode();
    }

	private Collection<RateRange> rateRange(List<ProviderRateInfoDTO> providerRateInfos) {
		return FunctionalIterables.make(providerRateInfos).map(Functions.of(rateRangeTranslator)).toCollection();
	}

    private Position position(PositionDTO position) {
        return new PositionTranslator().translate(position);
    }

    private Policy policy(HotelPolicyDTO hotelPolicy) {
        return new HotelPolicyTranslator().translate(hotelPolicy);
    }

    private ContactNumbers contactNumber(List<TelephoneDTO> telephoneDTOs) {
    	return FunctionalIterables.make(telephoneDTOs).inject(
    		new ContactNumbers(), 
    		new Injector<ContactNumbers, TelephoneDTO>() {
				public ContactNumbers apply(ContactNumbers memo, TelephoneDTO input) {
					TelephoneDTO2ContactNumberTranslator translator = new TelephoneDTO2ContactNumberTranslator();
					memo.getContactNumber().add(translator.translate(input)); 
					return memo;
				}
			}
    	);
    }

    private AddressInfoType addressInfo(AddressDTO address) {
        return new AddressRSTranslator().translate(address);
    }
}
